<!doctype html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport"
        content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
</head>
<body>
<div id="app">
  <p v-text="name"></p>
  <div v-text="name"></div>

  <div>
    <div>
      <div>
        <span>
          <div>
            <span>
              <p v-text="name"></p>
              <div>
                <span>
                  <span v-text="name"></span>
                </span>
              </div>
            </span>
          </div>
        </span>
      </div>
    </div>
    <span><p v-text="name"></p></span>
    <p v-text="name"></p>
  </div>

  <input type="text" v-model="name">
  <p v-text="age"></p>
</div>
<script>
  let data = {
    name: 'Tom',
    age: 19
  }

  // 使用订阅发布模式实现精准更新
  const Dep = {
    map: {},
    collect(eventName, fn) {
      if (!this.map[eventName]) {
        this.map[eventName] = []
      }
      this.map[eventName].push(fn)
    },
    trigger(eventName) {
      console.log('111111111')
      this.map[eventName].forEach(fn => fn())
    }
  }

  complied()
  Object.keys(data).forEach(key => {
    Observe(data, key, data[key])
  })

  function Observe(data, key, value) {
    Object.defineProperty(data, key, {
      get() {
        return value
      },
      set(newVal) {
        value = newVal
        Dep.trigger(key)
      }
    })
  }

  function complied() {
    // 得到app下的所有 子 节点
    const childNodes = document.getElementById('app').childNodes
    //const childNodes = document.querySelectorAll('*')
    // 获取标签节点
    const destinationNode = []
    // 获取
    childNodes.forEach(node => {
      // 1为标签节点
      if (node.nodeType === 1) {
        node.children.length ? getAllNode(node, destinationNode) : destinationNode.push(node)
      }
    })
    console.log(destinationNode)
    // 获取包含指令的标签
    destinationNode.forEach(tag => {
      const attrs = Array.from(tag.attributes)
      attrs.forEach(attr => {
        // v-text
        if (attr.nodeName === 'v-text' && attr.nodeValue) {
          tag.innerHTML = data[attr.nodeValue]
          Dep.collect(attr.nodeValue, () => tag.innerHTML = data[attr.nodeValue])
        }
        // v-module
        if (attr.nodeName === 'v-model' && attr.nodeValue) {
          tag.value = data[attr.nodeValue]
          Dep.collect(attr.nodeValue, () => tag.value = data[attr.nodeValue])
          tag.addEventListener('input', (e) => {
            data[attr.nodeValue] = e.target.value
          })
        }
      })
    })
  }

  // 可以使用querySelectorAll('*')直接获取所有标签节点 这里是练习递归
  function getAllNode(node, result) {
    Array.from(node.children).reduce((pre, cur) => {
      if (cur.children.length) {
        getAllNode(cur, result)
      } else {
        pre.push(cur)
      }
      return pre
    }, result)
  }
</script>

</body>
</html>
